﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bzure.Security.Principal;
using Bzure.Common.Data;
using Bzure.Common.Transactions;
using Bzure.Security;
using Bzure.Security.Principal;
using Bzure.Security.Permissions;
using Bzure.Apps.Security;


namespace Bzure.Apps.Security
{
    public static class DroitResourceExtensions
    {
        /// <summary>
        /// 根据资源名称获得资源列表
        /// </summary>
        /// <param name="Public"></param>
        /// <param name="ResourceName"></param>
        /// <returns></returns>
        public static DroitResource[] GetResourceByName(this Public Public, String ResourceName)
        {
            DroitResource resource = new DroitResource(String.Empty)
            {
                ResourceName = ResourceName
            };
            EntityQueryRequest<DroitResource> query = new EntityQueryRequest<DroitResource>();
            query.AppendConditionMap(resource.ResourceName, () => resource.ResourceName);
            return Actor.Public.BuildEntityProcessor("SecurityApp").QueryEntity(query);
        }
        #region reset droit resourc
        public static void ResetDroitResource(this Public Public, string ResourceName, DroitResource[] droits, Action<bool> action)
        {
            BizTransaction transaction = BizTransaction.BeginTransaction();
            //step 1 删除原有的授权配置
            RegisterFactor_DeleteOldDroits(transaction, ResourceName);
            //step 2 添加用户新的授权配置
            RegisterFactor_AddNewDroits(transaction, ResourceName, droits);
            bool ok = transaction.TryCommit();
            if (ok)
            {
                Actor.Public.UpdateLastPermissionChangeTime();
            }
            action(ok);
        }
        static void RegisterFactor_DeleteOldDroits(BizTransaction transaction, string resourceid)
        {
            IEntityRequestProcess deleteDroitsProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> deleteDroitsFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(deleteDroitsProcessor);
            deleteDroitsFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            deleteDroitsFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {

                EntityPostRequest deleteDroitRequest = BuilddeleteDroitRequest(resourceid);
                action(deleteDroitsProcessor, deleteDroitRequest);

            };

            transaction.RegisterFactor(deleteDroitsFactor);
        }
        static EntityPostRequest BuilddeleteDroitRequest(string resourceid)
        {
            DroitResource oldResource = new DroitResource(Guid.NewGuid().ToString())
            {
                ResourceName = resourceid
            };
            EntityPostRequest oldPostRequest = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Delete)
            {
                Entity = oldResource
            };
            oldPostRequest.AppendConditionMap(oldResource.ResourceName, () => oldResource.ResourceName);
            return oldPostRequest;
        }

        static void RegisterFactor_AddNewDroits(BizTransaction transaction, string ResourceName, DroitResource[] droits)
        {
            IEntityRequestProcess addDroitsProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> addDroitsFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(addDroitsProcessor);
            addDroitsFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            addDroitsFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {
                foreach (DroitResource droit in droits)
                {
                    EntityPostRequest addDroitRequest = BuildaddDroitRequest(ResourceName, droit);
                    action(addDroitsProcessor, addDroitRequest);
                }
            };

            transaction.RegisterFactor(addDroitsFactor);
        }
        static EntityPostRequest BuildaddDroitRequest(string ResourceName, DroitResource resource)
        {
            EntityPostRequest postRequest = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Create)
            {
                Entity = resource
            };
            postRequest.AppendFieldMap(resource.ResourceID, () => resource.ResourceID);
            postRequest.AppendFieldMap(resource.ResourceName, () => resource.ResourceName);
            postRequest.AppendFieldMap(resource.RoleID, () => resource.RoleID);
            postRequest.AppendFieldMap(resource.RightValue, () => resource.RightValue);
            postRequest.AppendFieldMap(resource.State, () => resource.State);
            return postRequest;
        }
        #endregion
    }
}
